package com.zhxy.gps.terminal;

import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zhxy.gps.terminal.message.AbstractMessage;
import com.zhxy.gps.terminal.message.AccessMessage;
import com.zhxy.gps.terminal.message.ReplyMessage;
import com.zhxy.util.async.ResultHandler;
import com.zhxy.util.message.AsyncMessageProcessor;
import com.zhxy.util.message.DuplexMessagePipe;
import com.zhxy.util.message.DuplexMessageServiceListener;
import com.zhxy.util.message.MessageCodec;
import com.zhxy.util.message.MessagePipe;
import com.zhxy.util.message.MessagePipeIoHandlerConfig;
import com.zhxy.util.message.MinaDuplexMessageService;

public class AbstractGatewayConnector implements DuplexMessageServiceListener, AsyncMessageProcessor<DuplexMessagePipe, Object> {
	
	private static final Logger logger = LoggerFactory.getLogger(AbstractGatewayConnector.class);
	
	private MinaDuplexMessageService service;
	
	private MessagePipe pipe;
	
	private String deviceSerial;
	
	private ScheduledExecutorService executorService;
	
	private MessageCodec messageCodec;

	public AbstractGatewayConnector() {
		

	}

	public String getDeviceSerial() {
		return deviceSerial;
	}

	public void setDeviceSerial(String deviceSerial) {
		this.deviceSerial = deviceSerial;
	}

	public ScheduledExecutorService getExecutorService() {
		return executorService;
	}

	public void setExecutorService(ScheduledExecutorService executorService) {
		this.executorService = executorService;
	}

	public void setMessageCodec(MessageCodec messageCodec) {
		this.messageCodec = messageCodec;
	}

	public void connect(InetSocketAddress address) {
		
		if (address == null)
			throw new IllegalArgumentException("address不可以是null");
		if (service != null)
			throw new IllegalStateException("已经连接服务器");
		
		MessagePipeIoHandlerConfig config = new MessagePipeIoHandlerConfig();
		config.setKeepAliveTime(5);
		
		NioSocketConnector connector = new NioSocketConnector();

		service = new MinaDuplexMessageService();
		service.setConfig(config);
		service.setCodec(messageCodec);
		service.setScheduledExecutor(executorService);
		service.addMessageProcessor(this);
		service.addDuplexMessageServiceListener(this);
		service.bindIoService(connector);
		
		logger.debug("开始连接服务器");

		connector.connect(address);
	}
	
	public void close() {
		if (service != null) {
			service.close();
			service.removeDuplexMessageServiceListener(this);
			service = null;
		}
	}
	
	@Override
	public void connected(DuplexMessagePipe pipe) {
		
		this.pipe = pipe;
		
		logger.debug("已连接服务器，准备发送access消息");
		
		AccessMessage access = new AccessMessage(deviceSerial);
		pipe.request(access, new ResultHandler<Object>() {
			public void result(Object result) {
				ReplyMessage reply = (ReplyMessage)result;
				if (reply.isSuccess()) {
					logger.debug("服务器验证成功:" + deviceSerial);
				} else {
					logger.debug("服务器验证失败:" + deviceSerial);
				}
			}
			public void exception(Throwable e) {
				logger.debug("服务器验证异常" + deviceSerial, e);
			}
		});
	}

	@Override
	public void disconnected(DuplexMessagePipe pipe) {

	}

	@Override
	public void process(DuplexMessagePipe pipe, Object message,
			ResultHandler<Object> handler) {
		
		logger.debug("虚拟终端接收到指令" + message);
//		if (message instanceof LocateMessage) {
//			pipe.send(locate(System.currentTimeMillis() - startTime));
//		}
		
		if (handler != null) {
			handler.result(new ReplyMessage(true));
		}
	}
	
	public void sendMessage(AbstractMessage message) {
		pipe.send(message);
	}
}
